/**
 * LayuiFormVirtualSelect 类 - 用于处理大数据量的select下拉选择器
 * 通过虚拟滚动技术优化性能，支持搜索和动态创建选项
 */
class LayuiFormVirtualSelect {
  /**
   * 构造函数 - 初始化选择器的配置和数据
   * @param {Object} options - 配置选项
   * @param {Object} options.selectName - select元素的名称映射
   * @param {Map|Object} options.dataMap - 选项数据映射
   * @param {Object} options.config - 虚拟滚动配置
   * @param {Object} options.form - layui的form实例
   */
  constructor(options = {}) {
    // this.selectName = options.selectName || {};
    this.dataMap =
      options.dataMap instanceof Map
        ? options.dataMap
        : new Map(Object.entries(options.dataMap || {}));
    this.searchTextMap = new Map();
    this.form = options.form;

    const configOptions = options.config || {};
    this.config = {
      itemHeight: configOptions.itemHeight || 42,
      visibleItems: configOptions.visibleItems || 10,
      bufferItems: configOptions.bufferItems || 5,
      maxHeight: configOptions.maxHeight || 300,
    };

    this.initData();
  }

  /**
   * 初始化所有select的数据
   * 使用requestAnimationFrame优化性能
   */
  initData() {
    this.dataMap.forEach((data, selectId) => {
      requestAnimationFrame(() => {
        this.loadVirtualOptions(selectId, data);
      });
    });
  }

  /**
   * 加载虚拟选项到指定的select元素
   * @param {string} selectId - select元素的ID
   * @param {Array} data - 选项数据数组
   */
  loadVirtualOptions(selectId, data) {
    const select = document.getElementById(selectId);
    const { itemHeight, visibleItems, bufferItems, maxHeight } = this.config;
    let startIndex = 0;
    let currentScrollTop = 0;
    let chooseValue = {};

    // 获取过滤后的数据
    const getFilterData = (searchText) => {
      if (!searchText) return this.dataMap.get(selectId) || [];
      const searchValue = searchText.toLowerCase();
      return (this.dataMap.get(selectId) || []).filter(
        (item) =>
          item.text.toLowerCase().includes(searchValue) ||
          String(item.value).toLowerCase().includes(searchValue)
      );
    };

    const updateVisibleOptions = (scrollTop) => {
      currentScrollTop = scrollTop;
      requestAnimationFrame(() => {
        const formSelect = select.nextElementSibling;
        const dl = formSelect.querySelector("dl.layui-anim");

        // 设置样式
        Object.assign(dl.style, {
          maxHeight: `${maxHeight}px`,
          overflowY: "auto"
        });

        // 计算索引
        startIndex = Math.floor(scrollTop / itemHeight);
        const start = Math.max(0, startIndex);
        const end = Math.min(data.length, startIndex + visibleItems + bufferItems);

        dl.innerHTML = "";

        // 添加上部空白
        if (start > 0) {
          const topSpacer = document.createElement("div");
          Object.assign(topSpacer.style, {
            height: `${start * itemHeight}px`,
            padding: "0",
            margin: "0"
          });
          dl.appendChild(topSpacer);
        }

        // 添加默认选项
        const defaultDd = document.createElement("dd");
        defaultDd.setAttribute("lay-value", "");
        defaultDd.textContent = "请选择";
        defaultDd.classList.add("layui-select-tips");
        dl.appendChild(defaultDd);

        // 处理空数据情况
        if (data.length === 0 && select.hasAttribute("lay-creatable")) {
          const searchText = this.searchTextMap.get(selectId);
          if (searchText) {
            dl.innerHTML = "";
            const dd = document.createElement("dd");
            dd.setAttribute("lay-value", searchText);
            dd.textContent = searchText;
            dl.appendChild(dd);
          }
        }

        // 添加可见选项
        for (let i = start; i < end; i++) {
          const dd = document.createElement("dd");
          dd.setAttribute("lay-value", data[i].value);
          dd.textContent = data[i].text;
          if (data[i].value == chooseValue.value) {//高亮当前选中项
            dd.classList.add("layui-this");
          }
          dl.appendChild(dd);
        }

        // 添加下部空白
        if (end < data.length) {
          const bottomSpacer = document.createElement("div");
          Object.assign(bottomSpacer.style, {
            height: `${(data.length - end) * itemHeight}px`,
            padding: "0",
            margin: "0"
          });
          dl.appendChild(bottomSpacer);
        }

        // 设置总高度
        const totalHeight = (data.length + 1) * itemHeight;
        dl.style.height = `${totalHeight}px`;
      });
    };

    const eventhandle = () => {
      const formSelect = select.nextElementSibling;
      const dl = formSelect.querySelector("dl.layui-anim");
      const title = formSelect.querySelector(".layui-select-title");
      const input = title.querySelector("input");

      // 选择事件处理
      this.form.on("select", (data) => {
        const curselectId = data.elem.id;
        if (curselectId !== selectId) return;

        const selectedDd = dl.querySelector(`dd[lay-value="${data.value}"]`);
        const selectedText = selectedDd ? selectedDd.textContent : "";
        
        input.setAttribute("placeholder", data.value ? selectedText : "请选择");
        this.searchTextMap.set(selectId, "");
        select.innerHTML = "";
        select.appendChild(new Option(selectedText, data.value, true, true));
        chooseValue = {
          value: data.value,
          text: selectedText,
        };
      });

      let ticking = false;

      // 点击事件处理
      const handleClick = () => {
        updateVisibleOptions(0);
      };

      // 搜索事件处理
      const handleSearch = (e) => {
        requestAnimationFrame(() => {
          const searchValue = e.target.value.toLowerCase();
          this.searchTextMap.set(selectId, searchValue);
          
          const filteredData = getFilterData(searchValue);
          data = filteredData;

          updateVisibleOptions(0);
          
          e.target.value = searchValue;
          e.target.focus();
        });
      };

      // 滚动事件处理
      const handleScroll = () => {
        if (!ticking) {
          requestAnimationFrame(() => {
            updateVisibleOptions(dl.scrollTop);
            ticking = false;
          });
          ticking = true;
        }
      };

      // 绑定事件
      dl.removeEventListener("scroll", handleScroll);
      dl.addEventListener("scroll", handleScroll);

      title.removeEventListener("click", handleClick);
      title.addEventListener("click", handleClick);

      input.removeEventListener("keyup", handleSearch);
      input.addEventListener("keyup", handleSearch);
    };

    // 初始化流程
    this.form.render("select");
    requestAnimationFrame(() => {
      setTimeout(() => {
        const formSelect = select.nextElementSibling;
        if (formSelect) {
          updateVisibleOptions(0);
          eventhandle();
        } else {
          console.warn(`选择器 ${selectId} 未正确初始化`);
        }
      }, 50);
    });
  }

  debounce(fn, delay = 500) {
    let timer = null;
    return (...args) => {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => fn.apply(this, args), delay);
    };
  }
}
